This is a race.
This bug is caused by multi-threaded
accessing to the non-thread-safe WeakHashMap class at org.codehaus.groovy.ast.ClassHelper#makeCached
More details about this bug are at GROOVY-4292
JIRA page.
org.codehaus.groovy.ast.ClassHelper
public static ClassNode makeCached(Class c){
final SoftReference<ClassNode> classNodeSoftReference = ClassHelperCache.classCache.get(c);
ClassNode classNode;
if (classNodeSoftReference == null || (classNode = classNodeSoftReference.get()) == null) {
classNode = new ClassNode(c);
ClassHelperCache.classCache.put(c, new SoftReference<ClassNode>(classNode));
VMPluginFactory.getPlugin().setAdditionalClassInformation(classNode);
}
return classNode;
}
The following code describes the root cause of the endless loop happened in
this bug.
t1 t2 private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest, boolean rehash) {
for (int j = 0; j < src.length; ++j) {
1 2 Entry<K,V> e = src[j];
src[j] = null;
3,18,23 5,10 while (e != null) {
4,19,24 6,11 Entry<K,V> next = e.next;
Object key = e.get();
if (key == null) {
...
} else {
...
int i = indexFor(e.hash, dest.length);
15,20,25 7,12 e.next = dest[i];
16,21,26 8,13 dest[i] = e;
}
17,22,27 9,14 e = next;
}
}
}
Precondition: there is a chain at src[j]: A-->B-->null, in the
current hash table.
This bug has been reproduced under groovy 1.7.9, JDK 1.6.0_33, JDK
1.7.0 and JDK 1.8.0.
Execute the following scripts to run
the test to reproduce the bug (assume the location of the groovy test
project is groovy_test_home).
Linux:
${groovy_test_home}/scripts/run4292.sh
[--threadnum arg] [--loops arg] [--monitoroff]
Windows:
%groovy_test_home%\scripts\run4292.bat [--threadnum arg]
[--loops arg] [--monitoroff]
The default argument values will be taken if not specified. For
example,
${groovy_test_home}/scripts/run4292.sh
is the same as
${groovy_test_home}/scripts/run4292.sh
--threadnum 4 --loops 5
| Option | Function | Default Value | Valid Values |
| --threadnum, -tn | thread number | 4 | integer |
| --loops, -l | loop number | 5 | integer |
| --monitoroff, -mo | Turn off to stop reporting bug messages and ending program
when the test runs into the expected concurrency bug which is an
endless loop. User has to terminate the program manually when this option is set. |